package com.slipper.util;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtil {
    /** 按 yyyy-MM-dd HH:mm:ss 格式化时间. */
    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    private static final String DATE_FORMAT = "yyyy-MM-dd";

    /**
     * 格式化时间.
     * @linkplain #DATE_TIME_FORMAT
     * @param date 要格式化的时间
     * @return 格式化后的字符串
     */
    public static String format(Date date, String format) {
        return date == null ? "" : new SimpleDateFormat(format).format(date);
    }

    /**
     * 格式化时间.
     * @linkplain #DATE_TIME_FORMAT
     * @param millis 要格式化的长整形时间
     * @return 格式化后的字符串
     */
    public static String format(Long millis, String format) {
        return millis == null ? "" : format(new Date(millis), format);
    }

    /**
     * 格式化日期 yyyy-MM-dd HH:mm:ss
     * @param millis 要格式化的时间，长整形
     * @return 格式化后的字符串
     */
    public static String formatTime(Long millis) {
        return millis == null ? "" : DateUtil.format(new Date(millis), DATE_TIME_FORMAT);
    }

    /**
     * 格式化日期 yyyy-MM-dd HH:mm:ss
     * @param millis 要格式化的时间，长整形
     * @param format 要格式化的格式
     * @return 格式化后的字符串
     */
    public static String formatTime(Long millis, String format) {
        return millis == null ? "" : DateUtil.format(new Date(millis), format);
    }

    /**
     * 格式化时间  yyyy-MM-dd HH:mm:ss
     * @linkplain #DATE_TIME_FORMAT
     * @param date 要格式化的时间
     * @return 格式化后的字符串
     */
    public static String formatTime(Date date) {
        return date == null ? "" : DateUtil.format(date, DATE_TIME_FORMAT);
    }

    /**
     * 格式化日期 yyyy-MM-dd
     * @param millis 要格式化的时间，长整形
     * @return 格式化后的字符串
     */
    public static String formatDate(Long millis) {
        return millis == null ? "" : DateUtil.format(new Date(millis), DATE_FORMAT);
    }

    /**
     * 格式化日期 yyyy-MM-dd
     * @param date 要格式化的时间
     * @return 格式化后的字符串
     */
    public static String formatDate(Date date) {
        return date == null ? "" : DateUtil.format(date, DATE_FORMAT);
    }

    /**
     * 格式化日期 yyyy-MM-dd.
     * @param date 要格式化的时间
     * @return 格式化后的字符串
     */
    public static String formatDate(java.sql.Date date) {
        return date == null ? "" : DateUtil.format(date, DATE_FORMAT);
    }

    /**
     * 格式化时间.
     * @linkplain #DATE_TIME_FORMAT
     * @return 格式化后的字符串
     */
    public static Date parseDate(String dateStr) throws ParseException {
        return dateStr == null || dateStr.isEmpty() ? null : DateUtil.getDateFormat(dateStr.length()).parse(dateStr);
    }
    
    /**
     * 格式化时间.
     * @linkplain #DATE_TIME_FORMAT
     * @return 格式化后的字符串
     */
    public static Date parseDate(String str, String format) throws ParseException {
        return Tool.isBlank(str) ? null : new SimpleDateFormat(format).parse(str);
    }

    /**
     * 根据时间显示长度获取解释对象
     */
    public static SimpleDateFormat getDateFormat(int length) {
        String parseString = "yyyy-MM-dd HH:mm:ss.SSS".substring(0, length);
        return new SimpleDateFormat(parseString);
    }

    /**
     * 返回从start到end相差的秒数，end>start时返回正数
     */
    public static int secondDiff(Long start, Long end) {
        if (start == null || end == null) {
            return 0;
        }
        long mills = end - start;
        return (int) (mills / 1000);
    }

    /**
     * 返回从start到end相差的秒数，end>start时返回正数
     */
    public static int secondDiff(Date start, Date end) {
        if (start == null || end == null) {
            return 0;
        }
        long mills = end.getTime() - start.getTime();
        return (int) (mills / 1000);
    }

    /**
     * 返回从start到end相差的日期，end>start时返回正数
     */
    public static int dayDiff(Long start, Long end) {
        if (start == null || end == null) {
            return 0;
        }

        long mills = end - start;
        return (int) (mills / (24 * 60 * 60 * 1000));
    }

    /**
     * 返回从start到end相差的日期，end>start时返回正数
     */
    public static int dayDiff(Date start, Date end) {
        if (start == null || end == null) {
            return 0;
        }

        long mills = end.getTime() - start.getTime();
        return (int) (mills / (24 * 60 * 60 * 1000));
    }

    /**
     * 获取second秒后的时间
     */
    public static Date getNextSecond(Date date, int second) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.SECOND, second);
        return calendar.getTime();
    }

    /**
     * 获取hour小时后的时间
     */
    public static Date getNextHour(Date date, int hour) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.HOUR_OF_DAY, hour);
        return calendar.getTime();
    }

    /**
     * 获取day天后的时间
     */
    public static Date getNextDay(Long date, int day) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    /**
     * 获取day天后的时间
     */
    public static Date getNextDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    /**
     * 获取month月后的时间
     */
    public static Date getNextMonth(Long date, int month) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date);
        calendar.add(Calendar.MONTH, month);
        return calendar.getTime();
    }

    /**
     * 获取month月后的时间
     */
    public static Date getNextMonth(Date date, int month) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.MONTH, month);
        return calendar.getTime();
    }

    /**
     * 获取year年后的时间
     */
    public static Date getNextYear(Long date, int year) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date);
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }

    /**
     * 获取year年后的时间
     */
    public static Date getNextYear(Date date, int year) {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(date.getTime());
        calendar.add(Calendar.YEAR, year);
        return calendar.getTime();
    }

    /**
     * 获取今天0时0分0秒的Date
     */
    public static Date getCurrDate() {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(new Date().getTime());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取昨天0时0分0秒的Date
     */
    public static Date getYestDate() {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(new Date().getTime());
        calendar.add(Calendar.DATE, -1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本周一的Date
     */
    public static Date getCurrMonday() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本月第一天0时0分0秒的Date
     */
    public static Date getCurrMonthFirst() {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(new Date().getTime());
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取本年第一天0时0分0秒的Date
     */
    public static Date getCurrYearFirst() {
        Calendar calendar = Calendar.getInstance(Locale.CHINA);
        calendar.setTimeInMillis(new Date().getTime());
        calendar.set(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    public static Map<String, String> currDate() {
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("currYear", Calendar.getInstance().get(Calendar.YEAR) + "");
        resultMap.put("currMonth", (Calendar.getInstance().get(Calendar.MONTH) + 1) + "");
        resultMap.put("currDay", (Calendar.getInstance().get(Calendar.DAY_OF_MONTH)) + "");
        resultMap.put("currDate", DateUtil.formatDate(new Date()));
        resultMap.put("currMonthFirst", DateUtil.formatDate(DateUtil.getCurrMonthFirst()));
        resultMap.put("first7Day", DateUtil.formatDate(DateUtil.getNextDay(new Date(), 6)));
        resultMap.put("first30Day", DateUtil.formatDate(DateUtil.getNextDay(new Date(), 29)));
        return resultMap;
    }

    public static long currentTimeMillis() {
        return System.currentTimeMillis();
    }

    public static String formatDuration(long duration) {
        return formatDuration(duration, "秒");
    }

    public static String formatDuration(long duration, String format) {
        if (duration < 1000) return duration + " 毫秒";

        duration = duration / 1000;
        int day = (int) Math.floor(duration * 1.0 / (24 * 60 * 60));
        int hour = (int) Math.floor((duration * 1.0 - day * 24 * 60 * 60) / (60 * 60));
        int minute = (int) Math.floor((duration * 1.0 - day * 24 * 60 * 60 - hour * 60 * 60) / 60);
        int second = (int) (duration - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60);

        String result = "";
        if (day > 0) {
            result += " " + day + " 天";
        }
        if (hour > 0) {
            result += " " + hour + " 小时";
        }
        if (minute > 0) {
            result += " " + minute + " 分";
            if ("分".equals(format)) {
                return result + "钟";
            }
        }
        if ("分".equals(format) && !result.isEmpty()) {
            return result;
        }

        if (second > 0) {
            result += " " + second + " 秒";
        }
        if (result.isEmpty()) {
            result += "0 秒";
        }
        return result;
    }

    public static void main(String[] args) {
        System.out.println(formatTime(getCurrYearFirst()));
    }
}
